본문으로 이동
메뉴 여닫기
환경 설정 메뉴 여닫기
개인 메뉴 여닫기
로그인하지 않음
지금 편집한다면 당신의 IP 주소가 공개될 수 있습니다.

싱글톤 패턴(Singleton Pattern)은 클래스의 인스턴스가 프로그램 전체에서 하나만 만들어지도록 보장하고, 그 인스턴스에 어디서든 접근할 수 있는 통로를 제공하는 생성 패턴이다.

싱글톤 패턴은 GoF 디자인 패턴의 생성(Creational) 패턴 다섯 가지 중 하나다. 설정 정보, 커넥션 풀, 로그 기록기처럼 프로그램 안에 여러 개가 있으면 오히려 문제가 되는 객체에 쓴다. 생성자를 외부에서 부를 수 없게 막고, 클래스가 스스로 만든 유일한 인스턴스를 정적(static) 메서드로 돌려준다.

요소 역할
private 생성자 외부에서 new 로 객체를 만들지 못하게 막는다
private static 필드 유일한 인스턴스를 담아 둔다. 클래스에 하나만 존재한다 → 자바 static
public static 접근 메서드 인스턴스가 없으면 만들고, 있으면 이미 만든 것을 돌려준다(getInstance(), get() 등)
class Connection {
    private static Connection _inst = null;
    private int count = 0;

    static public Connection get() {
        if (_inst == null) {
            _inst = new Connection();   // 처음 한 번만 생성
        }
        return _inst;                   // 이후에는 같은 객체를 반환
    }
    public void count() { count++; }
    public int getCount() { return count; }
}

public class Main {
    public static void main(String[] args) {
        Connection conn1 = Connection.get();
        conn1.count();
        Connection conn2 = Connection.get();
        conn2.count();
        Connection conn3 = Connection.get();
        conn3.count();
        conn1.count();
        System.out.print(conn1.getCount());   // 4
    }
}
  • conn1, conn2, conn3 은 이름만 다를 뿐 모두 같은 객체를 가리킨다. conn1 == conn2 는 true 다.
  • 그래서 어느 변수로 count() 를 부르든 같은 count 필드가 늘어난다. 네 번 불렀으므로 4가 출력된다.
  • count 자체는 static 이 아닌 인스턴스 필드다. 값이 공유되는 이유는 필드가 static 이어서가 아니라 인스턴스가 하나뿐이어서다.
방식 내용 특징
지연 초기화(Lazy) 처음 요청할 때 만든다(위 예제) 쓰지 않으면 만들지 않는다. 멀티스레드에서 동시에 들어오면 두 개가 만들어질 수 있다
이른 초기화(Eager) 클래스가 로드될 때 static 필드에서 바로 만든다 스레드에 안전하다. 쓰지 않아도 만들어진다
동기화 메서드 접근 메서드에 synchronized 를 붙인다 안전하지만 호출할 때마다 잠금 비용이 든다
DCL(Double-Checked Locking) null 검사 → 잠금 → 다시 null 검사. 필드는 volatile 생성 시점에만 잠근다
홀더(Holder) 클래스 내부 정적 클래스가 로드될 때 인스턴스를 만든다 지연 초기화이면서 스레드에 안전하다
enum enum Singleton { INSTANCE; } 직렬화·리플렉션으로도 두 번째 인스턴스를 만들 수 없다
  • 장점
    • 인스턴스가 하나라 메모리 낭비가 적고, 생성 비용이 큰 객체를 한 번만 만든다.
    • 여러 곳에서 같은 상태를 공유할 수 있다.
  • 단점
    • 사실상 전역 변수라 클래스 사이의 결합도가 높아진다.
    • 단위 테스트에서 가짜 객체로 바꾸기 어렵다.
    • 멀티스레드 환경에서는 생성 시점과 공유 상태의 동기화를 따로 신경 써야 한다.